/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#pragma once

#include "MeasureLuminanceCS.h"

/**
    @brief  Perform Rheinhard global tonemapping against input HDR image and write out result to the framebuffer.
    @author yakiimo02
    @date    2010/02/15
*/
class ToneMapCS
{
protected:
    struct SCREEN_VERTEX
    {
        D3DXVECTOR4 pos;
        D3DXVECTOR2 tex;
    };

    /**
        Constant buffer
    */
    struct ConstantBuf
    {
        float    fLogAvgLuminance;            // log average luminance
        float    fMaxLuminance;                // luminance max value
        float    fMiddleKey;                    // tonemap middle key        
        int        nToneMapEnable;                // enable tone mapping
        int        nControlBurnOut;            // control max luminance burn out
        char    padding[12];                // constant buf size needs to mult of 16-bytes 

        ConstantBuf() : fLogAvgLuminance( 0.0f ), fMaxLuminance( 0.0f ), fMiddleKey( 0.0f ), nToneMapEnable( 1 ), nControlBurnOut( 1 ) {};
    };

public:
    ToneMapCS();
    ~ToneMapCS();

    HRESULT OnCreateDevice( ID3D11Device* pd3dDevice );
    HRESULT OnResizedSwapChain( ID3D11Device* pd3dDevice, const int nWidth, const int nHeight );
    HRESULT    OnFrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, const DXGI_SURFACE_DESC* pBackBufferDesc, const int nWidth, const int nHeight );
    void    OnReleasingSwapChain();
    void    OnDestroyDevice();

    inline void SetpTextureSRV( ID3D11ShaderResourceView* pTextureSRV ) { m_pTextureSRV = pTextureSRV; }
    inline void SetMiddleKey( const float fMiddleKey ) { m_constantBuf.fMiddleKey = fMiddleKey; }
    inline void SetToneMapEnable( const bool bToneMapEnable ) { m_constantBuf.nToneMapEnable = bToneMapEnable; }
    inline void SetControlBurnOut( const bool bControlBurnOut ) { m_constantBuf.nControlBurnOut = bControlBurnOut; }

    inline MeasureLuminanceCS*    GetpMeasureLuminanceCS() { return &m_measureLuminance; }
    inline float                GetMiddleKey() const { return m_constantBuf.fMiddleKey; }
    inline bool                    GetToneMapEnable() const { return m_constantBuf.nToneMapEnable != 0; }
    inline bool                    GetControlBurnOut() const { return m_constantBuf.nControlBurnOut != 0; }

protected:
    void DrawFullScreenQuad( ID3D11DeviceContext* pd3dImmediateContext, ID3D11PixelShader* pPS, UINT Width, UINT Height );

protected:
    // geometry
    ID3D11InputLayout*          m_pQuadLayout;
    ID3D11Buffer*               m_pVB;
    // shader
    ID3D11VertexShader*            m_pQuadVS;
    ID3D11PixelShader*          m_pQuadPS;
    ID3D11SamplerState*         m_pSampleStateLinear;
    ID3D11ShaderResourceView*   m_pTextureSRV;
    
    ID3D11Buffer*               m_pConstantBuf;                 // Constant buffer D3D object
    ConstantBuf                    m_constantBuf;                    // Constant buffer values

    MeasureLuminanceCS            m_measureLuminance;                // Calculate avg log luminance and max luminance
};

extern ToneMapCS        g_toneMapCS;
